package net.yienyien.process.bpel.generator.dataFlow;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.xml.namespace.QName;

import net.yienyien.process.bpel.generator.Production;
import net.yienyien.process.dfm.Container;
import net.yienyien.process.dfm.DataFlow;
import net.yienyien.process.dfm.Part;



import org.eclipse.wst.wsdl.Definition;
import org.eclipse.wst.wsdl.Message;
import org.open.oasis.docs.wsbpel._2._0.process.abstract_.AbstractFactory;
import org.open.oasis.docs.wsbpel._2._0.process.abstract_.TCopy;
import org.open.oasis.docs.wsbpel._2._0.process.abstract_.TFrom;
import org.open.oasis.docs.wsbpel._2._0.process.abstract_.TTo;
import org.open.oasis.docs.wsbpel._2._0.process.abstract_.TVariable;

public class ContainerManager{
	
	private Map<Container, TVariable> map=new HashMap<Container, TVariable>();
	private Production production;
	private DataFlow df;
	
	public ContainerManager(Production production, DataFlow df) {
		this.production=production;
		this.df=df;
	}
	
	public void addContainer(Container container, TVariable var) {
		map.put(container, var);
	}
	
	public TCopy createCopy(Container srcC, Part fromP, Container tgtC, Part toP) {
		TCopy copy=AbstractFactory.eINSTANCE.createTCopy();
		TFrom from;
		TTo to;
		
		Message srcMsg=resolveMessageType((QName) getVariable(srcC).getMessageType());
		Message tgtMsg=resolveMessageType((QName) getVariable(tgtC).getMessageType());
		
		
		javax.wsdl.Part wFromP = srcMsg.getPart(fromP.getName());
		javax.wsdl.Part wToP= tgtMsg.getPart(toP.getName());
		
		//wFromP.getTypeName()
		
		from=createTFrom(srcC, fromP);
		to=createTTo(tgtC, toP);
		
		copy.setFrom(from);
		copy.setTo(to);
		return copy;
	}
	
	public TCopy createCopy(Container srcC, Container tgtC) {
		TCopy copy=AbstractFactory.eINSTANCE.createTCopy();
		TFrom from;
		TTo to;
		
		from=createTFrom(srcC);
		to=createTTo(tgtC);
		
		copy.setFrom(from);
		copy.setTo(to);
		return copy;
	}
	
	
	
	
	
	public TVariable getVariable(Container container) {
		return map.get(container);
	}
		
	private TFrom _createTFrom(Container container) {
		TVariable src=getVariable(container);
		TFrom from=null;
		if(src!=null) {
			from=AbstractFactory.eINSTANCE.createTFrom();
			from.setVariable(src.getName());
		}
		return from;
	}
	
	private TTo _createTTo(Container container) {
		TVariable tgt=getVariable(container);
		TTo to=null;
		if(tgt!=null) {
			to=AbstractFactory.eINSTANCE.createTTo();
			to.setVariable(tgt.getName());
		}
		return to;
	}
	
	
	public TFrom createTFrom(Container container) {
		TFrom from=_createTFrom(container);
		if(from!=null) from.setPart(getPart(container, null));
		return from;
	}
	
	public TTo createTTo(Container container) {
		TTo to=_createTTo(container);
		if(to!=null) to.setPart(getPart(container, null));
		return to;
	}
	
	public TFrom createTFrom(Container container, Part part) {
		TFrom from=_createTFrom(container);
		if(from!=null) from.setPart(getPart(container, part));
		return from;
	}
	
	public TTo createTTo(Container container, Part part) {
		TTo to=_createTTo(container);
		if(to!=null) to.setPart(getPart(container, part));
		return to;
	}
	
	private String getPart(Container container, Part part) {
		Message msg=resolveMessageType((QName) getVariable(container).getMessageType());
		
		if(part!=null && msg.getPart(part.getName())!=null) {
			return part.getName();
		} else for(Object o: msg.getParts().entrySet()) {
			Map.Entry e= (Entry) o;
			return (String) e.getKey();
		}
		return null;
	}
	
	
	private Message resolveMessageType(QName messageType) {
		for(Definition def:production.getWSDLs()) {
			Message msg=(Message) def.getMessage(messageType);
			if(msg!=null) {
				return msg;
			}
		}
		return null;
	}
	
	/* 
	<sequence>
	<invoke ... inputVariable="..." outputVariable="A" />
	<assign>
    <copy>
    <from>bpel:doXslTransform("urn:stylesheets:A2B.xsl", $A)</from>
    <to variable="B" />
    </copy>
    </assign>
    <invoke ... inputVariable="B" ... />
    </sequence>
      
	*/
	
}
